
#include  "stm32f0xx.h"
#include "bsp_usart.h"

/*******************USART编程要点*********************************************/
//使能RX和TX引脚GPIO时钟和USART时钟     		开时钟
//初始化GPIO，并将GPIO复用到USART上
//配置USART参数
//配置中断控制器并使能中断
//使能USART
//在USART中断服务函数中写相应的功能

//嵌套向量中断控制器初始化函数
// static	void	NVIC_Configuration(void)    //静态函数仅供本文件调用
// {
//     NVIC_InitTypeDef NVIC_InitStruct;     					//初始化NVIC结构体
//     NVIC_InitStruct.NVIC_IRQChannel=DEBUG_USART_IRQ;    	//中断号
//     NVIC_InitStruct.NVIC_IRQChannelPriority=0;              //抢占优先级1级
//     NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;             //使能中断
//     NVIC_Init(&NVIC_InitStruct );                         //执行初始化
// }

//USART初始化函数(使用USART点灯的过程中不用中断)
void	USART_Config(void)
{
    GPIO_InitTypeDef	GPIO_InitStruct;
    USART_InitTypeDef	USART_InitStruct;

    //开启相关外设的时钟
    DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK,ENABLE);    			//开启USART1的时钟
    DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK,ENABLE);   //开启GPIO的时钟

    /*
    PA9-TX-推挽复用
    PA10-RX-浮空输入/上拉输入
    */
    GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,GPIO_PinSource9,GPIO_AF_1);
    GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,GPIO_PinSource10,GPIO_AF_1);
    //配置USART的相应管脚的模式
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;          //Tx管脚
    GPIO_InitStruct.GPIO_Pin=DEBUG_USART_TX_GPIO_PIN;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_Level_3;
    GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;   
    GPIO_Init(DEBUG_USART_TX_GPIO_PORT,&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;          //Rx管脚
    GPIO_InitStruct.GPIO_Pin=DEBUG_USART_RX_GPIO_PIN;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_Level_3;
    GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;   
    GPIO_Init(DEBUG_USART_RX_GPIO_PORT,&GPIO_InitStruct);

    //配置串口的工作参数   即波特率=115200   数据长度=8bit    停止位=1bit   校验位=无  硬件流控制=无
    USART_InitStruct.USART_BaudRate=DEBUG_USART_BAUDRATE;
    USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;     //配置模式(收发一起)
    USART_InitStruct.USART_Parity=USART_Parity_No ;
    USART_InitStruct.USART_StopBits=USART_StopBits_1;
    USART_InitStruct.USART_WordLength=USART_WordLength_8b;

    USART_Init(DEBUG_USARTx,&USART_InitStruct);                 //DEBUG_USARTx一个结构体指针
    
    //开启USART中断
    //NVIC_Configuration();
    //选择具体的USART中断类型  (这个可靠吗???)
    //USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,ENABLE);  //空闲中断 (有好几个中断,都可引起USART中断)
    //使能USART
    USART_Cmd(DEBUG_USARTx,ENABLE);
}


//发送一个字符
void	USART_SendByte(USART_TypeDef *  USARTx,uint8_t  ch)
{   
    USART_SendData(USARTx,ch);
    //下面就是等待发送完成       //TXE发送寄存器为空(但移位寄存器可能并不为空)，发送单个字节的时候使用
    while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
}

//发送一个字符串  (以发送字符为基础)
void	USART_SendString(USART_TypeDef *  USARTx,int8_t *str)
{
    while((*str) !='\0')    //
    {
        USART_SendByte(USARTx,*str);
        ++str;
    }
    //TC发送完成(移位寄存器已空)，发送多个字节的时候使用
    while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
}

//下面得重写一些标准的C库函数(需要重写前面包含stdio.h吗)

//重定向c库函数printf到串口，重定向后可使用printf函数
int	fputc(int ch,FILE *f)    //这里的FILE *f其实没什么屌用
{
    USART_SendByte(DEBUG_USARTx,(uint8_t)ch);
    while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TXE)==RESET);  //等待发送完成
    return	ch;   //按标准返回
}

//重定向c库函数scanf到串口,重定向后可使用scanf,getchar等函数
int	fgetc(FILE	*f)
{   //这里是不用中断的
    while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_RXNE)==RESET);
    return USART_ReceiveData(DEBUG_USARTx);
}


// void DEBUG_USART_IRQHandler(void)
// {
//     //如果是接受中断  (一般发送不需要中断,连续发送)
//     if(USART_GetFlagStatus( DEBUG_USARTx,USART_FLAG_RXNE)==SET)    //如果是接受产生的中断
//     {
//         temp=USART_ReceiveData  (DEBUG_USARTx) ;  //接收到后马上返回去  (相应的中断标志会被清除，在读出数据后)
//         USART_SendByte(DEBUG_USARTx,temp);
//     }
// }
